using System;
using System.Text;
using System.Data;
using System.Transactions;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Web.Security;
using System.Web.Configuration;
using System.Globalization;
using System.Security.Cryptography;
using System.IO;
using System.Security.Principal;

using Microsoft.ConnectionEngine.Common.Security;
using Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common.DataSets;

namespace Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Business
{
    internal class AspnetMembershipUserManager
    {
        //Work Item ID: 53
        //Modified By: SachinJo
        private AspnetMembershipUserManager()
        {
            //Private constructor added to prevent the compiler from generating a default constructor.
        }

        #region Get/search methods

        /// <summary>
        /// Gets a user membership by ID
        /// </summary>
        /// <param name="userID">The ID of the user membership to retrieve</param>
        /// <returns>A user membership object representing the requested user</returns>
        internal static AspnetMembershipUser GetByUserID(Guid userID)
        {
            AspnetMembershipUser aspnetMembershipUser = null;

            // Load user data from database
            dsAspnetUser dataSet = DataAccess.AspnetUser.GetByUserID(userID);
            if (dataSet.aspnet_Users.Rows.Count > 0)
            {
                // Populate user data
                dsAspnetUser.aspnet_UsersRow dataRow = dataSet.aspnet_Users[0];
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateUserData(aspnetMembershipUser, dataRow);
                
                // Load and populate membership data
                AspnetMembershipUserManager.LoadMembershipData(aspnetMembershipUser);
            }
            return aspnetMembershipUser;
        }


        /// <summary>
        /// Gets a user membership by user name
        /// </summary>
        /// <param name="userName">The user name of the user membership to retrieve</param>
        /// <returns>A user object representing the requested user</returns>
        internal static AspnetMembershipUser GetByUserName(string userName)
        {
            AspnetMembershipUser aspnetMembershipUser = null;

            // Load user data from database
            dsAspnetUser dataSet = DataAccess.AspnetUser.GetByUserName(userName);
            if (dataSet.aspnet_Users.Rows.Count > 0)
            {
                // Populate user data
                dsAspnetUser.aspnet_UsersRow dataRow = dataSet.aspnet_Users[0];
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateUserData(aspnetMembershipUser, dataRow);

                // Load and populate membership data
                AspnetMembershipUserManager.LoadMembershipData(aspnetMembershipUser);
            }
            return aspnetMembershipUser;
        }


        /// <summary>
        /// Gets a user membership by email address
        /// </summary>
        /// <param name="email">The email address of the user membership to retrieve</param>
        /// <returns>A user membership object representing the requested user membership</returns>
        internal static AspnetMembershipUser GetByEmail(string email)
        {
            AspnetMembershipUser aspnetMembershipUser = null;

            // Load membership data from database
            dsAspnetMembership dataSet = DataAccess.AspnetMembership.GetByEmail(email);
            if (dataSet.aspnet_Membership.Rows.Count > 0)
            {
                // Populate membership data
                dsAspnetMembership.aspnet_MembershipRow dataRow = dataSet.aspnet_Membership[0];
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateMembershipData(aspnetMembershipUser, dataRow);

                // Load and user membership data
                AspnetMembershipUserManager.LoadUserData(aspnetMembershipUser);
            }
            return aspnetMembershipUser;
        }


        /// <summary>
        /// Gets every user membership from the database
        /// </summary>
        /// <returns>A user list object containing each user</returns>
        internal static List<AspnetMembershipUser> GetAll()
        {
            // Load from database
            dsAspnetUser dataSet = DataAccess.AspnetUser.GetAll();

            // Fill list with each row
            List<AspnetMembershipUser> userList = new List<AspnetMembershipUser>();
            foreach (dsAspnetUser.aspnet_UsersRow dataRow in dataSet.aspnet_Users)
            {
                // Populate user data
                AspnetMembershipUser aspnetMembershipUser = new AspnetMembershipUser();
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateUserData(aspnetMembershipUser, dataRow);

                // Load and populate membership data
                AspnetMembershipUserManager.LoadMembershipData(aspnetMembershipUser);

                // Add to collection
                userList.Add(aspnetMembershipUser);
            }
            return userList;
        }


        /// <summary>
        /// Returns a collection of all membership users in the database matching an email (or part of it)
        /// </summary>
        /// <param name="email">The email to find</param>
        /// <returns>A list of matching membership users</returns>
        internal static List<AspnetMembershipUser> FindByEmail(string email)
        {
            // Load from database
            dsAspnetMembership dataSet = DataAccess.AspnetMembership.GetByEmail(email + "%");

            // Fill list with each row
            List<AspnetMembershipUser> userList = new List<AspnetMembershipUser>();
            foreach (dsAspnetMembership.aspnet_MembershipRow dataRow in dataSet.aspnet_Membership)
            {
                // Populate membership data
                AspnetMembershipUser aspnetMembershipUser = new AspnetMembershipUser();
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateMembershipData(aspnetMembershipUser, dataRow);

                // Load and populate user data
                AspnetMembershipUserManager.LoadUserData(aspnetMembershipUser);

                // Add to collection
                userList.Add(aspnetMembershipUser);
            }
            return userList;
        }
        

        /// <summary>
        /// Returns a collection of all membership users in the database matching a username (or part of it)
        /// </summary>
        /// <param name="userName">The username to find</param>
        /// <returns>A list of matching membership users</returns>
        internal static List<AspnetMembershipUser> FindByUserName(string userName)
        {
            // Load from database
            dsAspnetUser dataSet = DataAccess.AspnetUser.GetByUserName(userName + "%");

            // Fill list with each row
            List<AspnetMembershipUser> userList = new List<AspnetMembershipUser>();
            foreach (dsAspnetUser.aspnet_UsersRow dataRow in dataSet.aspnet_Users)
            {
                // Populate user data
                AspnetMembershipUser aspnetMembershipUser = new AspnetMembershipUser();
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateUserData(aspnetMembershipUser, dataRow);

                // Load and populate membership data
                AspnetMembershipUserManager.LoadMembershipData(aspnetMembershipUser);

                // Add to collection
                userList.Add(aspnetMembershipUser);
            }
            return userList;
        }


        /// <summary>
        /// Loads and populates the properties of an AspnetMembershipUser object that come 
        /// from the membership table (assuming the user data has already been loaded)
        /// </summary>
        /// <param name="aspnetMembershipUser">The AspnetMembershipUser object to populate</param>
        internal static void LoadMembershipData(AspnetMembershipUser aspnetMembershipUser)
        {
            // load membership data into dataset
            dsAspnetMembership dataSet = DataAccess.AspnetMembership.GetByUserID(aspnetMembershipUser.UserID);

            // if at least one row, populate data
            if (dataSet.aspnet_Membership.Rows.Count > 0)
            {
                dsAspnetMembership.aspnet_MembershipRow dataRow = dataSet.aspnet_Membership[0];
                aspnetMembershipUser = AspnetMembershipUserManager.PopulateMembershipData(aspnetMembershipUser, dataRow);
            }
        }


        /// <summary>
        /// Loads and populates the properties of an AspnetMembershipUser object that come 
        /// from the user table (assuming the membership data has already been loaded)
        /// </summary>
        /// <param name="aspnetMembershipUser">The AspnetMembershipUser object to populate</param>
        internal static void LoadUserData(AspnetMembershipUser aspnetMembershipUser)
        {
            // load membership data into dataset
            dsAspnetUser dataSet = DataAccess.AspnetUser.GetByUserID(aspnetMembershipUser.UserID);
                
            // if at least one row, populate data
            if (dataSet.aspnet_Users.Rows.Count > 0)
            {
                dsAspnetUser.aspnet_UsersRow dataRow = dataSet.aspnet_Users[0];
                aspnetMembershipUser = PopulateUserData(aspnetMembershipUser, dataRow);
            }
        }


        /// <summary>
        /// Populates properties of an AspnetMembershipUser object from a membership datarow
        /// </summary>
        /// <param name="aspnetMembershipUser">The AspnetMembershipUser object to populate</param>
        /// <param name="dataRow">The datarow to fill from</param>
        /// <returns>The populated membership user</returns>
        internal static AspnetMembershipUser PopulateMembershipData(AspnetMembershipUser aspnetMembershipUser, dsAspnetMembership.aspnet_MembershipRow dataRow)
        {
            if (aspnetMembershipUser == null)
            {
                aspnetMembershipUser = new AspnetMembershipUser();
            }
            aspnetMembershipUser.UserID = dataRow.UserId;
            aspnetMembershipUser.ApplicationID = dataRow.ApplicationId;
            aspnetMembershipUser.Comment = dataRow.Comment;
            aspnetMembershipUser.CreateDate = dataRow.CreateDate;
            aspnetMembershipUser.Email = dataRow.Email;
            aspnetMembershipUser.FailedPasswordAnswerAttemptCount = dataRow.FailedPasswordAnswerAttemptCount;
            aspnetMembershipUser.FailedPasswordAnswerAttemptWindowStart = dataRow.FailedPasswordAnswerAttemptWindowStart;
            aspnetMembershipUser.FailedPasswordAttemptCount = dataRow.FailedPasswordAttemptCount;
            aspnetMembershipUser.FailedPasswordAttemptWindowStart = dataRow.FailedPasswordAttemptWindowStart;
            aspnetMembershipUser.IsApproved = dataRow.IsApproved;
            aspnetMembershipUser.IsLockedOut = dataRow.IsLockedOut;
            aspnetMembershipUser.LastLoginDate = dataRow.LastLoginDate;
            aspnetMembershipUser.LastLockoutDate = dataRow.LastLockoutDate;
            aspnetMembershipUser.LastPasswordChangedDate = dataRow.LastPasswordChangedDate;
            aspnetMembershipUser.LoweredEmail = dataRow.LoweredEmail;
            aspnetMembershipUser.MobilePIN = dataRow.MobilePIN;
            aspnetMembershipUser.Password = dataRow.Password;
            aspnetMembershipUser.PasswordAnswer = dataRow.PasswordAnswer;
            aspnetMembershipUser.PasswordFormat = dataRow.PasswordFormat;
            aspnetMembershipUser.PasswordQuestion = dataRow.PasswordQuestion;
            aspnetMembershipUser.PasswordSalt = dataRow.PasswordSalt;

            return aspnetMembershipUser;
        }


        /// <summary>
        /// Populates properties of an AspnetMembershipUser object from a user datarow
        /// </summary>
        /// <param name="aspnetMembershipUser">The AspnetMembershipUser object to populate</param>
        /// <param name="dataRow">The datarow to fill from</param>
        /// <returns>The populated membership user</returns>
        internal static AspnetMembershipUser PopulateUserData(AspnetMembershipUser aspnetMembershipUser, dsAspnetUser.aspnet_UsersRow dataRow)
        {
            if (aspnetMembershipUser == null)
            {
                aspnetMembershipUser = new AspnetMembershipUser();
            }
            aspnetMembershipUser.UserID = dataRow.UserId;
            aspnetMembershipUser.ApplicationID = dataRow.ApplicationId;
            aspnetMembershipUser.IsAnonymous = dataRow.IsAnonymous;
            aspnetMembershipUser.LastActivityDate = dataRow.LastActivityDate;
            aspnetMembershipUser.LoweredUserName = dataRow.LoweredUserName;
            aspnetMembershipUser.MobileAlias = dataRow.MobileAlias;
            aspnetMembershipUser.UserName = dataRow.UserName;
            aspnetMembershipUser.HCUID = dataRow.HCUID;
            aspnetMembershipUser.ProviderId = dataRow.ServiceProviderID;

            return aspnetMembershipUser;
        }

        #endregion

        #region Insert/update methods

        /// <summary>
        /// Updates the details of a single user
        /// </summary>
        /// <param name="aspnetMembershipUser">The user to update</param>
        internal static void Update(AspnetMembershipUser aspnetMembershipUser)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                DataAccess.AspnetUser.Update(aspnetMembershipUser);
                if (!aspnetMembershipUser.IsAnonymous)
                {
                    DataAccess.AspnetMembership.Update(aspnetMembershipUser);
                }
                scope.Complete();
            }
        }


        /// <summary>
        /// Inserts the details of a new user
        /// </summary>
        /// <param name="aspnetMembershipUser">The new user to insert</param>
        /// <returns>The newly added user</returns>
        internal static AspnetMembershipUser Insert(AspnetMembershipUser aspnetMembershipUser)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                if (aspnetMembershipUser.UserID == Guid.Empty)
                {
                    aspnetMembershipUser.UserID = Guid.NewGuid();
                }
                
                DataAccess.AspnetUser.Insert(aspnetMembershipUser);
                if (!aspnetMembershipUser.IsAnonymous)
                {
                    DataAccess.AspnetMembership.Insert(aspnetMembershipUser);
                }
                scope.Complete();
            }
            return aspnetMembershipUser;
        }

        #endregion

        #region Delete methods

        /// <summary>
        /// Deletes an existing user
        /// </summary>
        /// <param name="aspnetMembershipUser">The user to delete</param>
        internal static void Delete(AspnetMembershipUser aspnetMembershipUser)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                DataAccess.AspnetMembership.Delete(aspnetMembershipUser.UserID);                
                DataAccess.AspnetUser.Delete(aspnetMembershipUser.UserID);
                scope.Complete();
            }
        }

        #endregion

        #region Password related methods

        /// <summary>
        /// Validates a password against the password of a specific user membership
        /// </summary>
        /// <param name="aspnetMembershipUser">The user membership to validate</param>
        /// <param name="password">The password to test</param>
        /// <param name="passwordFormat">The encoding/encryption format of the password (Hashed/encrypted/plain)</param>
        /// <returns>True if the passwords match, otherwise false</returns>
        internal static bool ValidatePassword(AspnetMembershipUser aspnetMembershipUser, string password, MembershipPasswordFormat passwordFormat)
        {
            string realPassword = aspnetMembershipUser.Password;    // the real password of the user
            string testPassword = password;                         // the password to test


            switch (passwordFormat)
            {
                case MembershipPasswordFormat.Hashed:
                    testPassword = AspnetMembershipUserManager.EncodePassword(testPassword, passwordFormat);
                    break;
                case MembershipPasswordFormat.Encrypted:
                    realPassword = AspnetMembershipUserManager.DecodePassword(realPassword, passwordFormat);
                    break;
                case MembershipPasswordFormat.Clear:
                    break;
                default:
                    throw new Exception("Password format not supported.");
            }
            return (testPassword == realPassword);
        }


        /// <summary>
        /// Changes the password of a membership user
        /// </summary>
        /// <param name="aspnetMembershipUser">The user membership to chnage the password of</param>
        /// <param name="oldPassword">The old password</param>
        /// <param name="newPassword">The new password</param>
        /// <param name="passwordFormat">The encryption format of the password</param>
        /// <returns>True if successful</returns>
        internal static bool ChangePassword(AspnetMembershipUser aspnetMembershipUser, string oldPassword, string newPassword, MembershipPasswordFormat passwordFormat)
        {
            // Validate current password
            if (AspnetMembershipUserManager.ValidatePassword(aspnetMembershipUser, oldPassword, passwordFormat))
            {
                // Update new password
                aspnetMembershipUser.Password = AspnetMembershipUserManager.EncodePassword(newPassword, passwordFormat);
                AspnetMembershipUserManager.Update(aspnetMembershipUser);
                return true;
            }
            return false;
        }


        /// <summary>
        /// Changes the password hint question/answer of a user membership
        /// </summary>
        /// <param name="aspnetMembershipUser">The user membership to change</param>
        /// <param name="password">The password of the user to update</param>
        /// <param name="newPasswordQuestion">The new password hint question</param>
        /// <param name="newPasswordAnswer">The new password hint answer</param>
        /// <param name="passwordFormat">The encryption format of the password</param>
        /// <returns>True if successful</returns>
        internal static bool ChangePasswordQuestionAndAnswer(AspnetMembershipUser aspnetMembershipUser, string password, string newPasswordQuestion, string newPasswordAnswer, MembershipPasswordFormat passwordFormat)
        {
            // Validate password
            if (AspnetMembershipUserManager.ValidatePassword(aspnetMembershipUser, password, passwordFormat))
            {
                // Update new question and answer
                aspnetMembershipUser.PasswordQuestion = newPasswordQuestion;
                aspnetMembershipUser.PasswordAnswer = newPasswordAnswer;
                AspnetMembershipUserManager.Update(aspnetMembershipUser);
                return true;
            }
            return false;
        }


        /// <summary>
        /// Returns the password of a user (if the answer to the password question is correct)
        /// </summary>
        /// <param name="aspnetMembershipUser">The user membership to get the password of</param>
        /// <param name="answer">The answer to the user's password question</param>
        /// <param name="passwordFormat">The encrytpion format of the password</param>
        /// <returns>
        /// If the answer is correct, will return either the user's current password (if the password 
        /// format is encrypted or clear) or a new password (if the password format is hashed)
        /// </returns>
        internal static string GetPasswordByQuestionAnswer(AspnetMembershipUser aspnetMembershipUser, string answer, MembershipPasswordFormat passwordFormat)
        {
            
            // Validate pasword question answer
            //Work Item ID: 1593
            //Modified By: SachinJo
            //if (aspnetMembershipUser.PasswordAnswer.ToLower() == answer.ToLower())
            if (string.Compare(aspnetMembershipUser.PasswordAnswer, answer, true) == 0)
            {
                if (passwordFormat == MembershipPasswordFormat.Hashed)
                {
                    // Can't decode a hashed password, so set a new one and return it
                    return AspnetMembershipUserManager.ResetPassword(aspnetMembershipUser, passwordFormat);
                }
                else
                {
                    // Return decoded password
                    return AspnetMembershipUserManager.DecodePassword(aspnetMembershipUser.Password, passwordFormat);
                }
            }
            return string.Empty;
        }


        /// <summary>
        /// Resets the password of user membership to a system generated one
        /// </summary>
        /// <param name="aspnetMembershipUser">The user to reset the password of</param>
        /// <param name="passwordFormat">The encryption format of the password</param>
        /// <returns>The newly generated password</returns>
        internal static string ResetPassword(AspnetMembershipUser aspnetMembershipUser, MembershipPasswordFormat passwordFormat)
        {
            string[] passwords1 = new string[5] {"P!ums", "@pples", "Mel0ns", "Pe@rs", "Peache$"};
            string[] passwords2 = new string[5] {"Coconut$", "Orange$", "Cherr1es", "M@ndarins", "Fe1joas"};
            string newPassword = string.Empty;
            Random random = new Random(DateTime.Now.Millisecond);

            #region Generate random fruit based password.
            
            // Fruit are an important sources of both digestible and indigestible carbohydrates. The 
            // digestible carbohydrates are present largely in the form of sugars and starches while 
            // indigestible cellulose provides roughage which is important to normal digestion. Fruit 
            // are also important sources of minerals and certain vitamins, especially vitamins A 
            // and C. The precursors of vitamin A, including beta-carotene and certain other carotenoids, 
            // are to be found particularly in yellow-orange fruit.  Citrus fruit are excellent sources of 
            // vitamin C. Bananas also provide an important source of vitamin C for the diets of many 
            // countries. This is not so much due to the level of vitamin C in bananas which is not 
            // especially high but rather to the large quantities of bananas consumed.

            // Generate random fruit based password.  
            newPassword = random.Next(1, 9).ToString() + passwords1[random.Next(0, 4)] + "&" + random.Next(1, 9).ToString() + passwords2[random.Next(0, 4)];

            #endregion

            // Save password
            aspnetMembershipUser.Password = AspnetMembershipUserManager.EncodePassword(newPassword, passwordFormat);
            AspnetMembershipUserManager.Update(aspnetMembershipUser);
            
            // Return new password
            return newPassword;
        }


        /// <summary>
        /// Encrypts, Hashes, or leaves the password clear based on the PasswordFormat.
        /// </summary>
        /// <param name="password">The password to encode</param>
        /// <param name="passwordFormat">The format to encode as</param>
        /// <returns>The encoded password</returns>
        internal static string EncodePassword(string password, MembershipPasswordFormat passwordFormat)
        {
            string encodedPassword = password;

            switch (passwordFormat)
            {
                case MembershipPasswordFormat.Clear:
                    break;
                case MembershipPasswordFormat.Encrypted:
                    encodedPassword = AspnetMembershipUserManager.EncryptPassword(password);    
                    break;
                case MembershipPasswordFormat.Hashed:
                    HMACSHA1 hash = new HMACSHA1();
                    hash.Key = HexToByte("B00B1E5");  
                    encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
                    break;
                default:
                    throw new SystemException("Unsupported password format.");
            }

            return encodedPassword;
        }


        /// <summary>
        /// Decrypts or leaves the password clear based on the PasswordFormat.
        /// </summary>
        /// <param name="encodedPassword">The encoded password</param>
        /// <param name="PasswordFormat">The password format (clear or encoded)</param>
        /// <returns>The decoded password</returns>
        internal static string DecodePassword(string encodedPassword, MembershipPasswordFormat PasswordFormat)
        {
            string password = encodedPassword;

            switch (PasswordFormat)
            {
                case MembershipPasswordFormat.Clear:
                    break;
                case MembershipPasswordFormat.Encrypted:
                    password = AspnetMembershipUserManager.DecryptPassword(password);
                    break;
                case MembershipPasswordFormat.Hashed:
                    throw new SystemException("Cannot decode a hashed password.");
                default:
                    throw new SystemException("Unsupported password format.");
            }

            return password;
        }


        /// <summary>
        /// Converts a hexadecimal string to a byte array. 
        /// </summary>
        /// <param name="hexString">The hex string to convert</param>
        /// <returns>An array of bytes based on the hex string</returns>
        internal static byte[] HexToByte(string hexString)
        {
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }
            return returnBytes;
        }

        
        /// <summary>
        /// Encrypts a plain text password using Rijndael encryption and a hardcoded pass phrase and salt value
        /// </summary>
        /// <param name="plainTextPassword">The plain text password to encrypt</param>
        /// <returns>The encrypted password</returns>
        internal static string EncryptPassword(string plainTextPassword)
        {
            // TODO: Load these values from elsewhere? 
            // SaltValue from Membership table? Maybe machinekey for passphrase?
            string passPhrase = "IL0veFruit&Vegetables";
            string saltValue = "s@1tValue";
            string initVector = "@1B2c3D4e5F6g7H8";

            int keySize = 256;  
        
            
            // Convert strings into byte arrays.
            byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
            byte[] plainTextPasswordBytes = Encoding.Unicode.GetBytes(plainTextPassword);

            // Create passwordDerivedBytes, from which the key will be derived.
            PasswordDeriveBytes passwordDerivedBytes = new PasswordDeriveBytes(passPhrase, saltValueBytes, "MD5", 2);

            // Use the passwordDerivedBytes to generate pseudo-random bytes for the encryption key. 
            byte[] keyBytes = passwordDerivedBytes.GetBytes(keySize / 8);

            // Create uninitialized Rijndael encryption object.
            RijndaelManaged symmetricKey = new RijndaelManaged();

            // Set encryption mode to Cipher Block Chaining
            symmetricKey.Mode = CipherMode.CBC;

            // Generate encryptor from the existing key bytes and initialization vector. 
            ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);

            // Define memory stream (to hold encrypted data) and cryptographic stream 
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

            // Do encryption and convert from memory stream into byte array.
            cryptoStream.Write(plainTextPasswordBytes, 0, plainTextPasswordBytes.Length);
            cryptoStream.FlushFinalBlock();
            byte[] encryptedPasswordBytes = memoryStream.ToArray();

            // Close streams.
            memoryStream.Close();
            cryptoStream.Close();

            // Return encrypted data (converted into a base64-encoded string)
            return Convert.ToBase64String(encryptedPasswordBytes);
        }

        
        /// <summary>
        /// Decrypts an encrypted password into plain text using Rijndael encryption 
        /// (Uses a hardcoded pass-phrase and salt value)
        /// </summary>
        /// <param name="encryptedPassword">The encrypted password (duh)</param>
        /// <returns>A decrypted plain text password</returns>
        internal static string DecryptPassword(string encryptedPassword)
        {
            // TODO: Load these values from elsewhere? 
            // SaltValue from Membership table? Maybe machinekey for passphrase?
            string passPhrase = "IL0veFruit&Vegetables";
            string saltValue = "s@1tValue";
            string initVector = "@1B2c3D4e5F6g7H8";

            int keySize = 256;  

            // Convert strings into byte arrays.
            byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
            byte[] encryptedPasswordBytes = Convert.FromBase64String(encryptedPassword);

            // Create a passwordDerivedBytes from which the key will be derived. 
            PasswordDeriveBytes passwordDerivedBytes = new PasswordDeriveBytes(passPhrase, saltValueBytes, "MD5", 2);

            // Use the passwordDerivedBytes to generate pseudo-random bytes for the encryption key. 
            byte[] keyBytes = passwordDerivedBytes.GetBytes(keySize / 8);

            // Create uninitialized Rijndael encryption object.
            RijndaelManaged symmetricKey = new RijndaelManaged();

            // Set encryption mode to Cipher Block Chaining
            symmetricKey.Mode = CipherMode.CBC;

            // Generate decryptor from the existing key bytes and initialization vector. 
            ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);

            // Define memory stream (for holding encrypted data) and cryptographic stream
            MemoryStream memoryStream = new MemoryStream(encryptedPasswordBytes);
            CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);

            // Allocate a buffer long enough to hold decrpyted ciphertext
            byte[] plainTextPasswordBytes = new byte[encryptedPasswordBytes.Length];

            // Start decrypting.
            int decryptedByteCount = cryptoStream.Read(plainTextPasswordBytes, 0, plainTextPasswordBytes.Length);

            // Close both streams.
            memoryStream.Close();
            cryptoStream.Close();

            // Return decrypted string.   
            return Encoding.Unicode.GetString(plainTextPasswordBytes, 0, decryptedByteCount);
        }

        #endregion

        #region Other methods

        /// <summary>
        /// Returns the ID of an application based on its name (used for creating a new user)
        /// </summary>
        /// <param name="applicationName">The application name</param>
        /// <returns>The ID of the application</returns>
        internal static Guid GetApplicationID(string applicationName)
        {
            // TODO: Create seperate AspnetApplication classes and move this to there
            return DataAccess.AspnetUser.GetApplicationID(applicationName);
        }

        #endregion


        //#region ValidateUser
        //public static IPrincipal ValidateUser(string username, string password)
        //{
        //    IPrincipal principal = null;

        //    if (MembershipValidateUser(username, password))
        //    {
        //        principal = GetUserPrincipal(username);
        //    }
        //    else
        //    {
        //        //throw an exception - reason?
        //    }

        //    return principal;
        //}

        //public static IPrincipal GetUserPrincipal(string username)
        //{            
        //    IIdentity identity = null;
        //    string[] roles;            

        //    // Load user data from database
        //    AspnetMembershipUser aspnetMembershipUser = GetByUserName(userName);
        //    if (aspnetMembershipUser != null)
        //    {                
        //        identity = new HSDIdentity(aspnetMembershipUser.UserID, username, aspnetMembershipUser.HCUID,
        //            aspnetMembershipUser.ProviderId);                    

        //        //the roles
        //         //roles = GetRolesForUser(username);                
        //    }
        //    return new GenericPrincipal(identity, roles);
        //}

        //public static bool MembershipValidateUser(string userName, string password)
        //{
        //    // Load membership user data
        //    AspnetMembershipUser aspnetMembershipUser = AspnetMembershipUserManager.GetByUserName(userName);
        //    if (aspnetMembershipUser != null)
        //    {
        //        // Validate password
        //        if (AspnetMembershipUserManager.ValidatePassword(aspnetMembershipUser, password, passwordFormat))
        //        {                   
        //            return true;
        //        }
        //    }

        //    return false;
        //}
        //#endregion


    }
}
